import { PageContainer } from "@ant-design/pro-layout";
import { Button, Collapse, Form, Layout, Tabs } from "antd";
import ReactCodeMirror from '@uiw/react-codemirror'
import styles from "./index.less";
import { tokyoNight } from '@uiw/codemirror-theme-tokyo-night';
import DragPanel from "@/pages/diagnose/generate/Pannel/components/dragPanel";
import PreviewContainer from "@/pages/diagnose/generate/Pannel/components/previewContainer";
import { DndProvider } from "react-dnd";
import { HTML5Backend } from 'react-dnd-html5-backend'
import { useEffect, useState } from "react";
import { copyText, saveJsonFile } from "@/pages/diagnose/generate/Pannel/util";
import { componentConfigs } from "./component-config";
import { json, jsonParseLinter } from "@codemirror/lang-json";
import { linter } from "@codemirror/lint";
import { useIntl, FormattedMessage } from "umi";
import { ResizableBox } from "react-resizable";
import 'react-resizable/css/styles.css'
import { usePanelGeneratorStore } from "./store/panelGeneratorStore";
import { useMockStore } from "./store/mockData";
import { useGlobalVariablesStore } from "./store/glovalVariablesStore";

const { Sider, Content } = Layout
const { Panel } = Collapse

/**
 * Panel config generator
 * @returns 
 */
const PannelGenerator = () => {
    // replace all state management with zustand
    const configStore = usePanelGeneratorStore((state) => state.data)
    const setConfigStore = usePanelGeneratorStore((state) => state.setConfigStore)
    const mockStore = useMockStore((state) => state.data)
    const setMockStore = useMockStore((state) => state.setMockStore)
    const globalVariableStore = useGlobalVariablesStore((state) => state.data)
    const setGlobalVariableStore = useGlobalVariablesStore((state) => state.setGlobalVariableStore)
    const intl = useIntl()
    const [validJson, setValidJson] = useState(true)
    const [validJsonMock, setValidJsonMock] = useState(true)
    const [validJsonVariable, setValidJsonVariable] = useState(true)
    const [isDragging, setIsDragging] = useState(false)
    const changeConfig = (value) => {
        try {
            setConfigStore(JSON.parse(value))
            setValidJson(true)
        } catch (e) {
            setValidJson(false)
        }
    }
    const changeMock = (value) => {
        try {
            setMockStore(JSON.parse(value))
            setValidJsonMock(true)
        } catch (e) {
            setValidJsonMock(false)
        }
    }
    const changeVariable = (value) => {
        try {
            setGlobalVariableStore(JSON.parse(value))
            setValidJsonVariable(true)
        } catch (e) {
            setValidJsonVariable(false)
        }
    }

    useEffect(() => {
        let datas = {}
        // take all datas into mock
        Object.keys(componentConfigs).forEach((key) => {
            datas = { ...datas, ...componentConfigs[key].datas }
        })
        setMockStore({ datas: datas })
    }, [])

    return (
        <DndProvider backend={HTML5Backend}>
            <PageContainer title={intl.formatMessage({ id: 'pages.diagnose.generatePanel.title', defaultMessage: '面板配置生成器' })}
                extra={[
                    <Form style={{ display: "flex", gap: "1rem", alignItems: 'center' }}>
                        <Button onClick={() => {
                            copyText(JSON.stringify(configStore, null, 2))
                        }}><FormattedMessage id="pages.diagnose.generatePanel.copy" defaultMessage="复制" /></Button>
                        <Button type="primary" onClick={() => {
                            saveJsonFile(JSON.stringify(configStore, null, 2))
                        }}><FormattedMessage id='pages.diagnose.generatePanel.downloadConfig' defaultMessage="下载配置文件" /></Button>
                    </Form>
                ]}
            >
                <div className={styles.editorBody}>
                    <div
                        style={{ display: "flex", justifyContent: "flex-end" }}
                    >

                    </div>
                    <Layout className={styles.content}>
                        <Sider className={`${styles.section} ${styles.sidebar}`}>
                            <Collapse defaultActiveKey={["1", "2"]}>
                                <Panel header={intl.formatMessage({ id: 'pages.diagnose.generatePanel.taskform', defaultMessage: "诊断任务组件" })} key="1">
                                    <div className={styles.components}>
                                        {Object.keys(componentConfigs).map((key, index) =>
                                            componentConfigs[key].container === 'taskform' &&
                                            <DragPanel setIsDragging={setIsDragging} type={key} container="taskform" key={index} />
                                        )}
                                    </div>
                                </Panel>
                                <Panel header={intl.formatMessage({ id: 'pages.diagnose.generatePanel.panels', defaultMessage: '诊断结果面板组件' })} key="2">
                                    <div className={styles.components}>
                                        {
                                            Object.keys(componentConfigs).map((key, index) =>
                                                componentConfigs[key].container === 'panels' &&
                                                <DragPanel setIsDragging={setIsDragging} type={key} container="panels" key={index} />
                                            )
                                        }
                                    </div>
                                </Panel>
                            </Collapse>
                        </Sider>
                        <Content className={styles.section} style={{ overflowX: 'auto' }}>
                            <PreviewContainer isDragging={isDragging} />
                        </Content>
                        <ResizableBox className={styles.resize} axis="x" width={400} resizeHandles={['w']} handle={<div className={styles.resizeHandle}></div>}>
                            <div className={`${styles.section} ${styles.sidebar}`} style={{ maxHeight: `calc(100vh - 170px)`, flexGrow: '1' }}>
                                <Tabs
                                    defaultActiveKey="1"
                                    type="card"
                                    size='middle'
                                    style={{ height: '100%' }}
                                    items={[{
                                        label: intl.formatMessage({ id: 'pages.diagnose.generatePanel.panelsConfig', defaultMessage: '面板配置' }),
                                        key: '1',
                                        children: (
                                            <>
                                                <div
                                                    className={validJson ? styles.valid : styles.invalid}>{validJson ? intl.formatMessage({ id: 'pages.diagnose.generatePanel.jsonCorrect', defaultMessage: 'JSON 格式正确' }) : intl.formatMessage({ id: 'pages.diagnose.generatePanel.jsonIncorrect', defaultMessage: 'JSON 格式有误，请检查' })}</div>
                                                <ReactCodeMirror
                                                    onChange={changeConfig}
                                                    height="100%"
                                                    style={{ height: 'calc(100vh - 170px - 96px)', overflowY: 'auto' }}
                                                    value={JSON.stringify(configStore, null, 2)}
                                                    extensions={[json(), linter(jsonParseLinter())]}
                                                    theme={tokyoNight}
                                                />
                                            </>
                                        )
                                    }, {
                                        label: intl.formatMessage({ id: 'pages.diagnose.generatePanel.mockData', defaultMessage: 'Mock 数据导入' }),
                                        key: '2',
                                        children: (
                                            <>
                                                <div
                                                    className={validJsonMock ? styles.valid : styles.invalid}>{validJsonMock ? intl.formatMessage({ id: 'pages.diagnose.generatePanel.jsonCorrect', defaultMessage: 'JSON 格式正确' }) : intl.formatMessage({ id: 'pages.diagnose.generatePanel.jsonIncorrect', defaultMessage: 'JSON 格式有误，请检查' })}</div>
                                                <ReactCodeMirror
                                                    onChange={changeMock}
                                                    height="100%"
                                                    style={{ height: 'calc(100vh - 170px - 96px)', overflowY: 'auto' }}
                                                    value={JSON.stringify(mockStore, null, 2)}
                                                    extensions={[json(), linter(jsonParseLinter())]}
                                                    theme={tokyoNight}
                                                />
                                            </>
                                        )
                                    }, {
                                        label: intl.formatMessage({ id: 'pages.diagnose.generatePanel.globalVariables', defaultMessage: '全局环境变量' }),
                                        key: '3',
                                        children: (
                                            <>
                                                <div
                                                    className={validJsonVariable ? styles.valid : styles.invalid}>{validJsonVariable ? intl.formatMessage({ id: 'pages.diagnose.generatePanel.jsonCorrect', defaultMessage: 'JSON 格式正确' }) : intl.formatMessage({ id: 'pages.diagnose.generatePanel.jsonIncorrect', defaultMessage: 'JSON 格式有误，请检查' })}</div>
                                                <ReactCodeMirror
                                                    onChange={changeVariable}
                                                    height="100%"
                                                    style={{ height: 'calc(100vh - 170px - 96px)', overflowY: 'auto' }}
                                                    value={JSON.stringify(globalVariableStore, null, 2)}
                                                    extensions={[json(), linter(jsonParseLinter())]}
                                                    theme={tokyoNight}
                                                />
                                            </>
                                        )
                                    }]}
                                />

                            </div>
                        </ResizableBox>
                    </Layout>
                </div>
            </PageContainer>
        </DndProvider>
    );
};

export default PannelGenerator;
